﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Ashlen.Portal.Core;
using Ashlen.Portal.Core.DTO;
using Ashlen.Portal.Core.DataInterfaces;
using Ashlen.Portal.Data.SqlServer;
using System.Web.Mvc;
using System.Web.Caching;
using System.Web;

namespace Ashlen.Portal.Services
{
    /// <summary>
    /// The NewsService service contains news related functionality. It contains News business logic and instantiates the 
    /// INewsDao object to interact with the database.
    /// </summary>
    /// <author>Shailen Sukul</author>
    /// <date>08 Nov 2006</date>
    /// <remarks>- JSON cannot understand LINQ-ENTITY objects (recursion problem while serializing) so had to have the methods returning anonymous type.
    /// This returns a much simpler object for ex: Select(f => new { f.Id, f.Caption ...} in the Dao layer.
    /// The return is a string type, which is actually JSON formatted as string. Look at the Ashlen.Portal.Core.Service.ServiceResponse object to learn about
    /// the response type.
    /// The decision to use JSON over XML was purely for performance reasons (JSON has a much smaller footprint).
    /// </remarks>
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class NewsService : INewsService
    {
        private INewsDao _newsDao;
        public NewsService ()
        {
            _newsDao = new NewsDao();
        }

        /// <summary>
        /// Gets a list of News Sources
        /// </summary>
        /// <returns></returns>
        public string GetNewsSources()
        {
            ServiceResponse response = new ServiceResponse();
            try {
                OutgoingWebResponseContext Response = WebOperationContext.Current.OutgoingResponse;
                HttpResponseHeader cacheHeader = HttpResponseHeader.CacheControl;
                String cacheControlValue = String.Format("max-age={0}, must-revalidate", 1000);
                Response.Headers.Add(cacheHeader, cacheControlValue);
                WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
                response.IsSuccess = true;
                response.Payload = _newsDao.GetNewsSourcesJSON();
            }
            catch (Exception ex) {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }

        /// <summary>
        /// Gets a list of News Sections (Categories)
        /// </summary>
        /// <returns></returns>
        public string GetNewsSection() {
            ServiceResponse response = new ServiceResponse();
            try {
                OutgoingWebResponseContext Response = WebOperationContext.Current.OutgoingResponse;
                HttpResponseHeader cacheHeader = HttpResponseHeader.CacheControl;
                String cacheControlValue = String.Format("max-age={0}, must-revalidate", 1);
                Response.Headers.Add(cacheHeader, cacheControlValue);
                WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
                response.IsSuccess = true;
                response.Payload = _newsDao.GetNewsSectionJSON();
            }
            catch (Exception ex) {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }
        
        /// <summary>
        /// Update the hit count of a news item.
        /// </summary>
        /// <param name="id"></param>
        public void HitUpdate(string id) {
            try {
                OutgoingWebResponseContext Response = WebOperationContext.Current.OutgoingResponse;
                HttpResponseHeader cacheHeader = HttpResponseHeader.CacheControl;
                String cacheControlValue = String.Format("max-age={0}, must-revalidate", 1);
                Response.Headers.Add(cacheHeader, cacheControlValue);
                WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
                _newsDao.HitUpdate(Convert.ToInt32(id));
            }
            catch (Exception ex){ }
        }
        /// <summary>
        /// Searches for news.
        /// </summary>
        /// <param name="request">An object representing the search request</param>
        /// <returns>List of NewsFeed serialized as a JSON string</NewsFeed></returns>
        public string SearchNewsHeadlines(NewsSearchRequest request) {

            ServiceResponse response = new ServiceResponse();
            try {
                OutgoingWebResponseContext Response = WebOperationContext.Current.OutgoingResponse;
                HttpResponseHeader cacheHeader = HttpResponseHeader.CacheControl;
                String cacheControlValue = String.Format("max-age={0}, must-revalidate", 1);
                Response.Headers.Add(cacheHeader, cacheControlValue);
                WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
                int total;

                object ret;
                List<object> feeds = new List<object>();
                if (request.newsSources != null) {
                    // validations 
                    if (DateTime.Parse(request.startDate) > DateTime.Parse(request.endDate)) {
                        throw new ApplicationException("The start date cannot be more than the end date. Please correct and search again.");
                    }
                    else if (DateTime.Parse(request.endDate).Subtract(DateTime.Parse(request.startDate)).TotalDays > 10) {
                        throw new ApplicationException("Choose a date range of 10 days or less. Please correct and search again.");
                    }
                    foreach (int source in request.newsSources) {
                        total = 0;
                        if (request.searchValue == "null") { request.searchValue = null; }
                        feeds.Add(_newsDao.SearchNewsFeeds(request.section, source, 100, request.searchValue, 1,
                             DateTime.Parse((request.startDate + " 00:01 AM")),
                             DateTime.Parse((request.endDate + " 11:59 PM")), request.sortBy, out total));
                    }
                }
                response.IsSuccess = true;
                response.Payload = feeds;
            }
            catch (ApplicationException aEx) {
                response = Utility.GetErrorResponse(aEx);
                response.FriendlyErrorMessage = aEx.Message;
            }
            catch (Exception ex) {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }

        /// <summary>
        /// Loads news headlines based upon the type enumeration.
        /// </summary>
        /// <param name="sourceId"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public string GetNewsHeadlines(int sourceId, HeadlinesType type, NewsSortBy sortBy) {
            DateTime startDate;
            DateTime endDate;
            DateTime temp;
            ServiceResponse response = new ServiceResponse();
            try {
                switch (type) {
                    default:
                    case HeadlinesType.todaysHeadlines:
                        temp = DateTime.Now.ToUniversalTime().AddDays(-1);
                        startDate = new DateTime(temp.Year, temp.Month, temp.Day, 23, 59, 59);
                        temp = DateTime.Now.ToUniversalTime();
                        endDate = new DateTime(temp.Year, temp.Month, temp.Day, 23, 59, 59).ToUniversalTime();
                        break;
                    case HeadlinesType.topIn24Hours:
                        temp = DateTime.Now.ToUniversalTime().AddDays(-1);
                        startDate = new DateTime(temp.Year, temp.Month, temp.Day, 23, 59, 59);
                        temp = DateTime.Now.ToUniversalTime();
                        endDate = new DateTime(temp.Year, temp.Month, temp.Day, 23, 59, 59).ToUniversalTime();
                        break;
                    case HeadlinesType.topInWeek:
                        temp = DateTime.Now.ToUniversalTime().AddDays(((int)DateTime.Now.ToUniversalTime().DayOfWeek * -2));
                        startDate = new DateTime(temp.Year, temp.Month, temp.Day, 23, 59, 59);
                        temp = DateTime.Now.ToUniversalTime();
                        endDate = new DateTime(temp.Year, temp.Month, temp.Day, 23, 59, 59).ToUniversalTime();
                        break;
                }
                OutgoingWebResponseContext Response = WebOperationContext.Current.OutgoingResponse;
                HttpResponseHeader cacheHeader = HttpResponseHeader.CacheControl;
                String cacheControlValue = String.Format("max-age={0}, must-revalidate", 1);
                Response.Headers.Add(cacheHeader, cacheControlValue);
                WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
                response.Payload = _newsDao.GetNewsFeeds(sourceId, startDate, endDate, sortBy);
                response.IsSuccess = true;
            }
            catch (Exception ex) {
                response = Utility.GetErrorResponse(ex);
            }
            return Newtonsoft.Json.JavaScriptConvert.SerializeObject(response);
        }
    }
}
